﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Net.Sockets;
using System.Collections.ObjectModel;
using System.Reflection.Emit;
using System.Xml.Linq;
namespace USV_Ground_Monitor
{

    public partial class Form2 : Form
    {
        public class sensorInfo
        {
            public string direction;
            public string ec;
            public string leval;
            public string maxspeed;
            public string orp;
            public string ph;
            public string speed;
            public string tem;

        }
        public class rokerInfo
        {
            public string left_x;
            public string left_y;
            public string right_x;
            public string right_y;
            public string sw_a;
            public string sw_b;
            public string sw_c;
            public string sw_d;
            public string sw_e;
            public string sw_f;
            public string sw_g;

        }

        public class stateInfo
        {
            public string bat_voltage;
            public string heading;
            public string latitude;
            public string longitude;
            public string speed;

        }
        public class newinfo
        {
            public sensorInfo env_sensor;
            public rokerInfo rocker;
            public stateInfo usv_state;

        }

        private StreamWriter logWriter;
        //定义窗体的长和宽，用于控件自适应
        private float X;//定义宽度
        private float Y;//定义高度
        public Form2()
        {
            InitializeComponent();
            // 初始化日志写入器
            logWriter = new StreamWriter("sensor_log.txt", true);
            logWriter.AutoFlush = true;
        }

        private void setTag(Control cons)//用于获取控件的大小和字体大小，我从网上炒的
        {
            foreach (Control con in cons.Controls)
            {
                con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;
                if (con.Controls.Count > 0)
                    setTag(con);
            }
        }

        private void setControls(float newx, float newy, Control cons)//用于设定在全新的窗口大小情况下的控件的大小和字体大小，我从网上炒的
        {
            foreach (Control con in cons.Controls)
            {
                if (con.Tag == null)
                    continue;
                string[] mytag = con.Tag.ToString().Split(new char[] { ':' });
                float a = System.Convert.ToSingle(mytag[0]) * newx;
                con.Width = (int)a;
                a = System.Convert.ToSingle(mytag[1]) * newy;
                con.Height = (int)a;
                a = System.Convert.ToSingle(mytag[2]) * newx;
                con.Left = (int)a;
                a = System.Convert.ToSingle(mytag[3]) * newy;
                con.Top = (int)a;
                Single currentSize = System.Convert.ToSingle(mytag[4]) * newy;
                con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
                if (con.Controls.Count > 0)
                    setControls(newx, newy, con);
            }
        }

        private void Form2_Load(object sender, EventArgs e)//当窗口加载时，获取控件大小，我找网上超的
        {
            X = this.Width;
            Y = this.Height;
            setTag(this);
        }

        private void Form2_Resize(object sender, EventArgs e)//当窗口变化时，改变控件大小，我找网上超的
        {
            float newx = (this.Width) / X;
            float newy = (this.Height) / Y;
            setControls(newx, newy, this);
        }

        private void InitializePortSelection(SerialPort serialPort)
        {
            if (serialPort == serialPort1)
            {
                serialPort1.PortName = cboPortName.Text;
                serialPort1.BaudRate = int.Parse(cboBaudRate.Text);
                serialPort1.DataBits = int.Parse(cboData.Text);
                serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), cboTest.Text);
                serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStop.Text);
            }
            else if (serialPort == serialPort2)
            {
                serialPort2.PortName = cboPortName2.Text;
                serialPort2.BaudRate = int.Parse(cboBaudRate2.Text);
                serialPort2.DataBits = int.Parse(cboData2.Text);
                serialPort2.Parity = (Parity)Enum.Parse(typeof(Parity), cboTest2.Text);
                serialPort2.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStop2.Text);
            }
        }

        private void btnScan_Click(object sender, EventArgs e)
        {
            string[] portNames = SerialPort.GetPortNames();
            cboPortName.Items.Clear();
            cboPortName.Items.AddRange(portNames);
            if (portNames.Length > 0)
                cboPortName.Text = portNames[0];
        }

        private void btnOpenPort_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();
                btnOpenPort.Text = "打开串口";
                panel2.BackColor = Color.Red;
            }
            else
            {
                InitializePortSelection(serialPort1);
                try
                {
                    if (IsPortInUse(serialPort1.PortName))
                    {
                        MessageBox.Show("端口已被占用！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    serialPort1.Open();
                    btnOpenPort.Text = "关闭串口";
                    panel2.BackColor = Color.Green;
                    MessageBox.Show("串口初始化成功！");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private bool IsPortInUse(string portName)
        {
            try
            {
                using (var port = new SerialPort(portName))
                {
                    port.Open();
                    port.Close();
                    return false;
                }
            }
            catch
            {
                return true;
            }
        }

        private void btnClearRec_Click(object sender, EventArgs e)
        {
            txtReceive.Text = string.Empty;
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (btnOpenPort.Text != "关闭串口")
            {
                MessageBox.Show("请打开串口");
                return;
            }

            byte[] buffer = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x04 };
            byte[] crc = CRC16LH(buffer, 6);
            //拼接buffer和crc
            byte[] buffer2 = new byte[8];
            buffer2[0] = buffer[0];
            buffer2[1] = buffer[1];
            buffer2[2] = buffer[2];
            buffer2[3] = buffer[3];
            buffer2[4] = buffer[4];
            buffer2[5] = buffer[5];
            buffer2[6] = crc[0];
            buffer2[7] = crc[1];
            serialPort1.Write(buffer2, 0, 8);

            string result = BitConverter.ToString(buffer2).Replace("-", " ");
            AppendToReceiveBox($"TX1:-> {result}", Color.Blue);
        }

        private static byte[] CRC16LH(byte[] pDataBytes, int length)
        {
            ushort crc = 0xFFFF;
            ushort polynom = 0xA001;

            for (int i = 0; i < length; i++)
            {
                crc ^= pDataBytes[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 0x01) == 0x01)
                    {
                        crc >>= 1;
                        crc ^= polynom;
                    }
                    else
                    {
                        crc >>= 1;
                    }
                }
            }
            return BitConverter.GetBytes(crc);
        }

        private void cbxAutoRead_CheckedChanged(object sender, EventArgs e)
        {
            if (cbxAutoRead.Checked)
            {
                if (!serialPort1.IsOpen)
                {
                    timer1.Stop(); // 停止定时器
                    cbxAutoRead.Checked = false; // 取消勾选
                    MessageBox.Show("请先打开串口！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                timer1.Interval = Convert.ToInt32(textBox3.Text); // 设置定时器间隔
                timer1.Start(); // 启动定时器
            }
            else
            {
                timer1.Stop(); // 停止定时器
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // 检查串口是否打开
            if (!serialPort1.IsOpen)
            {
                // 停止定时器
                timer1.Stop();
                cbxAutoRead.Checked = false; // 取消勾选
                //MessageBox.Show("串口已关闭，定时读取已停止！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            else btnSend_Click(sender, e);
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                List<byte> tempBytes = new List<byte>();
                while (serialPort1.BytesToRead > 0)
                {
                    byte[] buffer = new byte[serialPort1.BytesToRead];
                    serialPort1.Read(buffer, 0, buffer.Length);
                    tempBytes.AddRange(buffer);
                    Thread.Sleep(80); // 超时时间
                }

                byte[] recData = tempBytes.ToArray();
                int[] sensorData = ParseRTUData(recData);
                UpdateTextBox(txtWindSpeed, (sensorData[0] / 100.0f).ToString("F2"));
                UpdateTextBox(txtWindDirection, sensorData[1].ToString());
                UpdateTextBox(txtMaxWindSpeed, (sensorData[2] / 100.0f).ToString("F2"));
                UpdateTextBox(txtWindLevel, sensorData[3].ToString());

                // 更新折线图
                UpdateChartWindSpeed(sensorData[0] / 100.0f, sensorData[2] / 100.0f);

                // 更新风向圆盘
                DrawWindDirection(sensorData[1]);
                string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - 风速: {sensorData[0] / 100.0f:F2} m/s, 风向: {sensorData[1]}°, 最大风速: {sensorData[2] / 100.0f:F2} m/s, 风力等级: {sensorData[3]} 级\r\n";
                logWriter.WriteLine(logEntry);

                string result = BitConverter.ToString(recData).Replace("-", " ");
                AppendToReceiveBox($"RX1:-> {result}", Color.Red);

                panel3.BackColor = Color.Blue;
                Thread.Sleep(20);
                panel3.BackColor = Color.White;
            }
            catch (System.InvalidOperationException ex)
            {
                // 捕获“端口被关闭”异常
                MessageBox.Show("串口1已关闭，数据接收中断！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception ex)
            {
                // 捕获其他异常
                MessageBox.Show($"数据接收错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private int[] ParseRTUData(byte[] bytes)
        {
            int[] sensorData = new int[4];
            for (int i = 0; i < 4; i++)
            {
                sensorData[i] = (bytes[3 + i * 2] << 8) | bytes[4 + i * 2];
            }
            return sensorData;
        }

        private void UpdateTextBox(System.Windows.Forms.TextBox textBox, string text)
        {
            if (textBox.InvokeRequired)
            {
                textBox.BeginInvoke(new Action(() => textBox.Text = text));
            }
            else
            {
                textBox.Text = text;
            }
        }

        private void AppendToReceiveBox(string text, Color color)
        {
            txtReceive.BeginInvoke(new Action(() =>
            {
                txtReceive.SelectionStart = txtReceive.TextLength;
                txtReceive.SelectionColor = color;
                txtReceive.AppendText($"[{DateTime.Now:HH:mm:ss.fff}] {text}\r\n");
                txtReceive.ScrollToCaret();
            }));
        }

        private void UpdateChartWindSpeed(float realTimeWindSpeed, float maxWindSpeed)
        {
            // 检查是否需要调用 Invoke
            if (chartWindSpeed.InvokeRequired)
            {
                // 使用委托调用自身，确保在 UI 线程中执行
                chartWindSpeed.BeginInvoke(new Action(() => UpdateChartWindSpeed(realTimeWindSpeed, maxWindSpeed)));
                return;
            }

            // 添加实时风速数据
            chartWindSpeed.Series["RealTimeWindSpeed"].Points.AddY(realTimeWindSpeed);

            // 添加最大风速数据
            chartWindSpeed.Series["MaxWindSpeed"].Points.AddY(maxWindSpeed);

            // 限制数据点数量，避免图表过长
            if (chartWindSpeed.Series["RealTimeWindSpeed"].Points.Count > 50)
            {
                chartWindSpeed.Series["RealTimeWindSpeed"].Points.RemoveAt(0);
                chartWindSpeed.Series["MaxWindSpeed"].Points.RemoveAt(0);
            }

            // 刷新图表
            chartWindSpeed.Update();
        }

        private void UpdateChartTemperature(float PH, float temperature)
        {
            if (chartTemperature.InvokeRequired)
            {
                chartTemperature.BeginInvoke(new Action(() => UpdateChartTemperature(PH, temperature)));
                return;
            }

            // 添加PH数据
            chartTemperature.Series["PH"].Points.AddY(PH);

            chartTemperature.Series["Temperature"].Points.AddY(temperature);

            // 限制数据点数量，避免图表过长
            if (chartTemperature.Series["PH"].Points.Count > 50)
            {
                chartTemperature.Series["PH"].Points.RemoveAt(0);
                chartTemperature.Series["Temperature"].Points.RemoveAt(0);
            }

            // 刷新图表
            chartTemperature.Update();
        }

        private void UpdateChartEC(int ORP, int EC)
        {
            if (chartEC.InvokeRequired)
            {
                chartEC.BeginInvoke(new Action(() => UpdateChartEC(ORP, EC)));
                return;
            }

            // 添加ORP数据
            chartEC.Series["ORP"].Points.AddY(ORP);

            chartEC.Series["EC"].Points.AddY(EC);

            // 限制数据点数量，避免图表过长
            if (chartEC.Series["ORP"].Points.Count > 50)
            {
                chartEC.Series["ORP"].Points.RemoveAt(0);
                chartEC.Series["EC"].Points.RemoveAt(0);
            }

            // 刷新图表
            chartEC.Update();

        }

        private void DrawWindDirection(int windDirection)
        {
            if (panelWindDirection.InvokeRequired)
            {
                panelWindDirection.BeginInvoke(new Action(() => DrawWindDirection(windDirection)));
                return;
            }

            using (Graphics g = panelWindDirection.CreateGraphics())
            {
                g.Clear(panelWindDirection.BackColor);
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                int diameter = Math.Min(panelWindDirection.Width, panelWindDirection.Height) - 10;
                int x = (panelWindDirection.Width - diameter) / 2;
                int y = (panelWindDirection.Height - diameter) / 2;

                // 绘制圆盘
                g.DrawEllipse(Pens.Black, x, y, diameter, diameter);

                // 绘制方向刻度
                string[] directions = { "N", "NE", "E", "SE", "S", "SW", "W", "NW" };
                for (int i = 90; i < -270; i -= 45)
                {
                    double angle = i * Math.PI / 180;
                    int x1 = (int)(x + diameter / 2 + (diameter / 2 - 10) * Math.Cos(angle));
                    int y1 = (int)(y + diameter / 2 + (diameter / 2 - 10) * Math.Sin(angle));
                    int x2 = (int)(x + diameter / 2 + (diameter / 2) * Math.Cos(angle));
                    int y2 = (int)(y + diameter / 2 + (diameter / 2) * Math.Sin(angle));
                    g.DrawLine(Pens.Black, x1, y1, x2, y2);

                    // 绘制方向文字
                    int textX = (int)(x + diameter / 2 + (diameter / 2 - 30) * Math.Cos(angle));
                    int textY = (int)(y + diameter / 2 + (diameter / 2 - 30) * Math.Sin(angle));
                    g.DrawString(directions[i / 45], new Font("Arial", 8), Brushes.Black, textX, textY);
                }

                // 绘制风向指针
                double pointerAngle = windDirection * Math.PI / 180;
                int pointerX = (int)(x + diameter / 2 + (diameter / 2 - 20) * Math.Cos(pointerAngle));
                int pointerY = (int)(y + diameter / 2 + (diameter / 2 - 20) * Math.Sin(pointerAngle));
                g.DrawLine(Pens.Red, x + diameter / 2, y + diameter / 2, pointerX, pointerY);
            }
        }

        private void serialPort2_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                List<byte> tempBytes = new List<byte>();
                while (serialPort2.BytesToRead > 0)
                {
                    byte[] buffer = new byte[serialPort2.BytesToRead];
                    serialPort2.Read(buffer, 0, buffer.Length);
                    tempBytes.AddRange(buffer);
                    Thread.Sleep(80); // 超时时间
                }

                byte[] recData = tempBytes.ToArray();
                int[] sensorData = ParseRTUData(recData);
                UpdateTextBox(txtPH, (sensorData[0] / 100.0f).ToString("F2"));
                UpdateTextBox(txtTemperature, (sensorData[1] / 10.0f).ToString());
                UpdateTextBox(txtORP, (sensorData[2]).ToString("F2"));
                UpdateTextBox(txtEC, sensorData[3].ToString());

                // 更新折线图
                UpdateChartTemperature(sensorData[0] / 100.0f, sensorData[1] / 10.0f);
                UpdateChartEC(sensorData[2], sensorData[3]);

                string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - PH: {sensorData[0] / 100.0f:F2} , 温度: {sensorData[1] / 10.0f:F2}℃, ORP: {sensorData[2] / 100.0f:F2} mV, EC: {sensorData[3]} us/cm\r\n";
                logWriter.WriteLine(logEntry);

                string result = BitConverter.ToString(recData).Replace("-", " ");
                AppendToReceiveBox($"RX2:-> {result}", Color.Red);

                panel5.BackColor = Color.Blue;
                Thread.Sleep(20);
                panel5.BackColor = Color.White;
            }
            catch (System.InvalidOperationException ex)
            {
                // 捕获“端口被关闭”异常
                MessageBox.Show("串口2已关闭，数据接收中断！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception ex)
            {
                // 捕获其他异常
                MessageBox.Show($"数据接收错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnScan2_Click(object sender, EventArgs e)
        {
            string[] portNames = SerialPort.GetPortNames();
            cboPortName2.Items.Clear();
            cboPortName2.Items.AddRange(portNames);
            if (portNames.Length > 0)
                cboPortName2.Text = portNames[0];
        }

        private void btnOpenPort2_Click(object sender, EventArgs e)
        {
            if (serialPort2.IsOpen)
            {
                serialPort2.Close();
                btnOpenPort2.Text = "打开串口2";
                panel6.BackColor = Color.Red;
            }
            else
            {
                InitializePortSelection(serialPort2);
                try
                {
                    if (IsPortInUse(serialPort2.PortName))
                    {
                        MessageBox.Show("端口已被占用！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                    serialPort2.Open();
                    btnOpenPort2.Text = "关闭串口2";
                    panel6.BackColor = Color.Green;
                    MessageBox.Show("串口2初始化成功！");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            // 检查串口是否打开
            if (!serialPort2.IsOpen)
            {
                // 停止定时器
                timer2.Stop();
                cbxAutoRead2.Checked = false; // 取消勾选
                //MessageBox.Show("串口2已关闭，定时读取已停止！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            else btnSend2_Click(sender, e);
        }

        private void btnClearRec2_Click(object sender, EventArgs e)
        {
            txtReceive.Text = string.Empty;
        }

        private void btnSend2_Click(object sender, EventArgs e)
        {
            if (btnOpenPort2.Text != "关闭串口2")
            {
                MessageBox.Show("请打开串口2");
                return;
            }

            byte[] buffer = { 0x02, 0x03, 0x00, 0x00, 0x00, 0x04 };
            byte[] crc = CRC16LH(buffer, 6);
            //拼接buffer和crc
            byte[] buffer2 = new byte[8];
            buffer2[0] = buffer[0];
            buffer2[1] = buffer[1];
            buffer2[2] = buffer[2];
            buffer2[3] = buffer[3];
            buffer2[4] = buffer[4];
            buffer2[5] = buffer[5];
            buffer2[6] = crc[0];
            buffer2[7] = crc[1];
            serialPort2.Write(buffer2, 0, 8);

            string result = BitConverter.ToString(buffer2).Replace("-", " ");
            AppendToReceiveBox($"TX2:-> {result}", Color.Blue);
        }

        private void cbxAutoRead2_CheckedChanged(object sender, EventArgs e)
        {
            if (cbxAutoRead2.Checked)
            {
                if (!serialPort2.IsOpen)
                {
                    timer2.Stop(); // 停止定时器
                    cbxAutoRead2.Checked = false; // 取消勾选
                    MessageBox.Show("请先打开串口！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                timer2.Interval = Convert.ToInt32(textBox3.Text); // 设置定时器间隔
                timer2.Start(); // 启动定时器
            }
            else
            {
                timer2.Stop(); // 停止定时器
            }
        }

        private void Form2_FormClosing(object sender, FormClosingEventArgs e)
        {
            logWriter?.Dispose();
        }
        public static Socket server_recv;
        IPEndPoint ip;
        //public int m_UDP_Recv_Port = 8081;
        string se;
        EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号
        byte[] buffer = new byte[1024];
        bool isConnect = false;
        private void btnExchange_Click(object sender, EventArgs e)
        {

            try
            {
                if (!isConnect)
                {
                    server_recv = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                    int m_UDP_Recv_Port = int.Parse(txtUDPPort.Text);
                    ip = new IPEndPoint(IPAddress.Any, m_UDP_Recv_Port);
                    server_recv.Bind(ip);//绑定端口号和IP
                    server_recv.ReceiveTimeout = 15000;
                    Thread t = new Thread(ReciveMsg);//开启接收消息线程
                    t.Start();
                    isConnect = true;
                    btnExchange.Text = "UDP关闭";
                }
                else
                {   
                    server_recv.Close();
                    isConnect = false;
                    btnExchange.Text = "UDP连接";
                }
                

            }
            catch
            {

            }
                
        }
        private void ReciveMsg()
        {
            while (true)
            {
                try
                {
                    int len = server_recv.ReceiveFrom(buffer, ref point);//接收数据
                }
                catch (SocketException ex)
                {
                    if (ex.SocketErrorCode == SocketError.TimedOut)
                    {
                        continue;
                    }
                    else
                    {
                        MessageBox.Show("接收数据错误：" + ex.Message);
                        break;
                    }
                
                }
                if (buffer.Length >= 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF)
                {

                    byte[] withoutBOM = new byte[buffer.Length - 3];
                    Array.Copy(buffer, 3, withoutBOM, 0, withoutBOM.Length);
                    buffer = withoutBOM;

                }


                se = Encoding.UTF8.GetString(buffer);
                //string jsonString = "";
                if (se.Contains("direction"))
                {
                    try
                    {
                        panel1.BackColor = Color.Blue;
                        newinfo myDeserializedClass = JsonConvert.DeserializeObject<newinfo>(se);
                        // 提取json中的env_sensor类的direction键的string数据
                        string direction = myDeserializedClass.env_sensor.direction;
                        string ec = myDeserializedClass.env_sensor.ec;
                        string leval = myDeserializedClass.env_sensor.leval;
                        string maxspeed = myDeserializedClass.env_sensor.maxspeed;
                        string orp = myDeserializedClass.env_sensor.orp;
                        string ph = myDeserializedClass.env_sensor.ph;
                        string speed = myDeserializedClass.env_sensor.speed;
                        string tem = myDeserializedClass.env_sensor.tem;
                        string heading = myDeserializedClass.usv_state.heading;
                        UpdateTextBox(txtPH, ph);
                        UpdateTextBox(txtTemperature, tem);
                        UpdateTextBox(txtORP, orp);
                        UpdateTextBox(txtEC, ec);

                        // 更新折线图
                        UpdateChartTemperature(float.Parse(ph), float.Parse(tem));
                        UpdateChartEC(int.Parse(orp), int.Parse(ec));

                        string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - PH: {ph} , 温度: {tem}℃, ORP: {orp} mV, EC: {ec} us/cm\r\n";
                        logWriter.WriteLine(logEntry);
                        UpdateTextBox(txtWindSpeed, speed);
                        UpdateTextBox(txtWindDirection, direction);
                        UpdateTextBox(txtMaxWindSpeed, maxspeed);
                        UpdateTextBox(txtWindLevel, leval);

                        // 更新折线图
                        UpdateChartWindSpeed(float.Parse(speed), float.Parse(maxspeed));
                        int windDirection = int.Parse(direction) - (int)(float.Parse(heading) / 3.14159265358979323846 * 180);
                        // 更新风向圆盘
                        DrawWindDirection(windDirection);
                        logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - 风速: {speed} m/s, 风向: {windDirection}°, 最大风速: {maxspeed} m/s, 风力等级: {leval} 级\r\n";
                        logWriter.WriteLine(logEntry);
                        Thread.Sleep(20);
                        panel1.BackColor = Color.White;
                    }
                    catch (JsonReaderException ex)
                    {
                        Console.WriteLine($"JSON解析错误: {ex.Message}");
                        // 处理异常，比如重新获取数据或记录日志
                    }

                    // 绘制风向指针
                }

            }
        }
    }
}
